/**
 * 
 */
package com.vivid.dynamics.oknow.test.dao;

import java.io.Serializable;
import java.util.Date;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.vivid.dynamics.junit.impl.SpringHibernateSupportJUnitTemplate;
import com.vivid.dynamics.oknow.dao.IUserCategoryDAO;
import com.vivid.dynamics.oknow.dao.IUserDAO;
import com.vivid.dynamics.oknow.model.User;
import com.vivid.dynamics.oknow.model.UserCategory;

/**
 *
 * @author jason
 * created at:: Aug 12, 2011 3:48:56 PM
 */
public class UserNUserCategoryTestCase extends SpringHibernateSupportJUnitTemplate {
	/**
	 * IUserDAO, check the config under config/spring-config.xml
	 */
	private @Autowired IUserDAO userDAO;
	/**
	 * IUserCategoryDAO, check the config under config/spring-config.xml
	 */
	private @Autowired IUserCategoryDAO userCategoryDAO;	
	
	/**
	 * ctor.
	 */
	public UserNUserCategoryTestCase() {
		super(UserNUserCategoryTestCase.class, true);
	}
	
	User userA=null;
	Serializable userAKey=null;
	
	/**
	 * creating default entities: in this case, the User object.
	 * 
	 * @author jason
	 * created at:: Aug 15, 2011  2:52:07 PM
	 */
	protected void createDefaultEntities() {
		this.userA=new User("jonathan", "joestar", false, "RootAdmin->default", "abc@abc.com", null);
		this.userAKey=this.userDAO.newUser(this.userA);
		this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
	}
	
	/**
	 * normal creation of User-Category(s)
	 * 
	 * @author jason
	 * created at:: Aug 15, 2011  2:52:30 PM
	 */
	@Test
	public void doTest001() {
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserNUserCategoryTestCase.doTest001}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		UserCategory aCat001=null;
		UserCategory aCat002=null;
		Serializable aCat001Key=null;
		Serializable aCat002Key=null;
		
		try {
			this.createDefaultEntities();
			this.sb.append("1) create normal UserCategories for UserA:\r\n");
			
			aCat001=new UserCategory("rocket science;physics");
			aCat002=new UserCategory("fiction;books;grade 4 or above readers");
			/*
			 * association
			 */
			this.userA.addUserCategory(aCat001);
			this.userA.addUserCategory(aCat002);
			/*
			 * creation of UserCategory(s) and update User 
			 */
			aCat001Key=this.userCategoryDAO.newUserCateogry(aCat001);
			aCat002Key=this.userCategoryDAO.newUserCateogry(aCat002);
			this.userDAO.updateUser(this.userA);
			
			// re-query
			aCat001=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat001Key);
			aCat002=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat002Key);
			this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
			
			this.sb.append("UserA :: ").append(this.userA).append("\r\n");
			this.createToStringForCollections(this.sb, this.userA.getUserCategories());
			this.sb.append("\r\n\r\ncat001 :: ").append(aCat001).append("\r\n\t").append(aCat001.getUser()).
				append("\r\n\r\ncat002 :: ").append(aCat002).append("\r\n\t").append(aCat002.getUser()).append("\r\n");
			
			/*
			 * 2) swap ordering; check the "userCatIdx"
			 */
			this.sb.append("2) swap ordering; check the \"userCatIdx\" :: check the ordering on the INDEX in the debug log~\r\n\r\n");
			this.userA.removeUserCategory(aCat001);
			this.userA.addUserCategory(aCat001);
			this.userDAO.updateUser(this.userA);
			
			// re-query
			aCat001=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat001Key);
			aCat002=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat002Key);
			this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
			
			this.sb.append("UserA :: ").append(this.userA).append("\r\n");
			this.createToStringForCollections(this.sb, this.userA.getUserCategories());
			this.sb.append("\r\n\r\ncat001 :: ").append(aCat001).append("\r\n\t").append(aCat001.getUser()).
				append("\r\n\r\ncat002 :: ").append(aCat002).append("\r\n\t").append(aCat002.getUser()).append("\r\n");
			
			this.tx.flush();
			
		} catch (RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
	
	/**
	 * update and delete of UserCategories
	 * 
	 * @author jason
	 * created at:: Aug 15, 2011  3:36:57 PM
	 */
	@Test
	public void doTest002() {
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserNUserCategoryTestCase.doTest002}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		UserCategory aCat001=null;
		UserCategory aCat002=null;
		Serializable aCat001Key=null;
		Serializable aCat002Key=null;
		
		try {
			this.createDefaultEntities();
			this.sb.append("1) create normal UserCategories for UserA:\r\n");
			
			aCat001=new UserCategory("rocket science;physics");
			aCat002=new UserCategory("fiction;books;grade 4 or above readers");
			/*
			 * association
			 */
			this.userA.addUserCategory(aCat001);
			this.userA.addUserCategory(aCat002);
			/*
			 * creation of UserCategory(s) and update User 
			 */
			aCat001Key=this.userCategoryDAO.newUserCateogry(aCat001);
			aCat002Key=this.userCategoryDAO.newUserCateogry(aCat002);
			this.userDAO.updateUser(this.userA);
			
			// re-query
			aCat001=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat001Key);
			aCat002=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat002Key);
			this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
			
			this.sb.append("UserA :: ").append(this.userA).append("\r\n");
			this.createToStringForCollections(this.sb, this.userA.getUserCategories());
			this.sb.append("\r\n\r\ncat001 :: ").append(aCat001).append("\r\n\t").append(aCat001.getUser()).
				append("\r\n\r\ncat002 :: ").append(aCat002).append("\r\n\t").append(aCat002.getUser()).append("\r\n");
			
			/*
			 * 2) update the UserCategories
			 */
			this.sb.append("\r\n2) updating; check the \"keyMeta\" :: key-meta changes; added 1 entry~\r\n\r\n");
			aCat001.setKeyMeta(aCat001.getKeyMeta()+";created @ "+new Date());
			aCat002.setKeyMeta(aCat002.getKeyMeta()+";created @ "+new Date());
			/*
			 * 1) since not n-to-n relationships; any side can do the update
			 * 2) since not affecting associations; either side can do the update
			 * PS. in case it involves associations... call on the owner side...
			 */
			this.userCategoryDAO.updateUserCategory(aCat001);
			this.userCategoryDAO.updateUserCategory(aCat002);
			
			// re-query
			aCat001=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat001Key);
			aCat002=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat002Key);
			this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
			
			this.sb.append("UserA :: ").append(this.userA).append("\r\n");
			this.createToStringForCollections(this.sb, this.userA.getUserCategories());
			this.sb.append("\r\n\r\ncat001 :: ").append(aCat001).append("\r\n\t").append(aCat001.getUser()).
				append("\r\n\r\ncat002 :: ").append(aCat002).append("\r\n\t").append(aCat002.getUser()).append("\r\n");
			
			/*
			 * 3) removal of UserCategory(s); really need to delete, since UserCategory can't exist alone
			 */
			this.sb.append("\r\n3) removing :: \r\n\r\n");
			this.userA.removeUserCategory(aCat002);
			this.userCategoryDAO.deleteUserCategory(aCat002);
			this.userDAO.updateUser(this.userA);
			// re-query
			aCat001=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat001Key);
			aCat002=this.userCategoryDAO.getUserCategoryByKey((Integer) aCat002Key);
			this.userA=this.userDAO.getUserByKey((Integer) this.userAKey);
			
			this.sb.append("UserA :: ").append(this.userA).append("\r\n");
			this.createToStringForCollections(this.sb, this.userA.getUserCategories());
			this.sb.append("\r\n\r\ncat001 :: ").append(aCat001).append("\r\n\t").append(aCat001.getUser()).
				append("\r\n\r\ncat002 :: ").append(aCat002).append("\r\n\r\n");
			Assert.assertTrue("3) aCat002 should be NULL now~ really removed from datasource.", aCat002==null);
			
			this.tx.flush();
			
		} catch (RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}			
	}
	
}
